using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Web.Mvc;
using System.Globalization;
using Stimulus360.Services;
using Stimulus360.Models.Data;
using System.Web.Configuration;
using Stimulus360.Services.Interfaces;

namespace Stimulus360.Controllers.Users
{  
    [HandleError]
    public class UsersController : Controller
    {
        /// <summary>
        ///     Instance of UserProfileService to be used
        /// </summary>
        private readonly IUserService _userProfileService;

        /// <summary>
        ///     Instance of MembershipService to be used
        /// </summary>
        private readonly IMembershipService _membershipService;

        /// <summary>
        ///     The number ideas and projects being shown in the screen
        /// </summary>
        private readonly string _pageSize = WebConfigurationManager.AppSettings["PageSize"];

        /// <summary>
        ///     Default controller to instantiate the services
        /// </summary>
        public UsersController()
        {
            _userProfileService = new UserService();
            _membershipService = new MembershipService();
        }

        /// <summary>
        ///     DI enabled constructor to inject instance of IUserService and IMembershipService to be used
        /// </summary>
        /// <param name="userService">
        ///     The IUserService instance
        /// </param>
        /// <param name="membershipService">
        ///     The IMembershipService instance
        /// </param>
        public UsersController(IUserService userService, IMembershipService membershipService)
        {
            _userProfileService = userService ?? new UserService();
            _membershipService = membershipService ?? new MembershipService();

        }
        /// <summary>
        ///     Method to redirect the user to the profile view
        /// </summary>
        /// <returns>
        ///     Redirects to the Profile view.
        /// </returns>
        [Authorize]
        public ActionResult Index()
        {
            return RedirectToAction("Profile", "Users", new { userName = User.Identity.Name });
        }

        /// <summary>
        ///     GET method to update the user profile
        /// </summary>
        /// <param name="userName">
        ///     Name of the user
        /// </param>
        /// <returns>
        ///     GET view model for updating the user profile
        /// </returns>
        [Authorize]
        public ActionResult Edit(string userName)
        {
            UserProfile user = _userProfileService.FindByUserName(userName);
            StringBuilder categoryIds = new StringBuilder();

            foreach (UserInterest interest in user.UserInterests)
            {
                categoryIds.Append(interest.CategoryId);
                categoryIds.Append("|");
            }

            UserProfileViewModel viewModel = new UserProfileViewModel
            {
                User = user,
                UserInterests = user.UserInterests.InterestSummary(),
                MinPasswordLength = _membershipService.MinPasswordLength,
                InvestmentCategories = _userProfileService.GetAllInvestmentCategories(),
                CategoryIds = categoryIds.ToString()
            };
            RemoveSession("userImage");
            return View(viewModel);
        }

        /// <summary>
        ///     POST Method to update the user profile
        /// </summary>
        /// <param name="interests">
        ///     Updated user interset
        /// </param>
        /// <param name="userName">
        ///     Name of the user
        /// </param>
        /// <returns>
        ///      Model with new user profile
        /// </returns>
        [ValidateAntiForgeryToken]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(string interests, string userName)
        {
            UserProfile user = new UserProfile();
            UpdateModel(user);

            if (!user.EditIsValid)
            {
                ModelState.AddModelError(user.GetEditRuleViolations());
            }
            else
            {

                if (!string.IsNullOrEmpty(user.OldPassword) && !string.IsNullOrEmpty(user.Password))
                {
                    if (_membershipService.ChangePassword(user.UserName, user.OldPassword, user.Password))
                    {
                        ModelState.AddModelError("OldPassword", "The old password not changed.");
                    }
                }

                _userProfileService.Update(user, interests);

                //***Code to save the user image...
                var userImageData = (byte[])HttpContext.Session["userImage"];
                if (userImageData != null)
                    _userProfileService.SaveUserThumbnail(userName, userImageData);

                return RedirectToAction("Index", "Users");
            }

            UserProfile userProfile = _userProfileService.FindByUserName(user.UserName);
            userProfile.OldPassword = user.OldPassword;
            userProfile.Password = user.Password;
            userProfile.ConfirmPassword = user.ConfirmPassword;
            StringBuilder categoryIds = new StringBuilder();

            foreach (UserInterest interest in userProfile.UserInterests)
            {
                categoryIds.Append(interest.CategoryId);
                categoryIds.Append("|");
            }

            UserProfileViewModel model = new UserProfileViewModel
            {
                User = userProfile,

                UserInterests = userProfile.UserInterests.InterestSummary(),
                MinPasswordLength = _membershipService.MinPasswordLength,
                InvestmentCategories = _userProfileService.GetAllInvestmentCategories(),
                CategoryIds = categoryIds.ToString()
            };



            return View(model);

        }

        /// <summary>
        ///     Method to save the user image
        /// </summary>
        /// <returns>
        ///     User image to be rendered on the screen
        /// </returns>
        public ActionResult SaveImage()
        {
            var filename = Server.MapPath("~/") + @"Content\images\projHeadImg.png";

            var userImage = Request.Files["userFileUpload"];
            if (userImage == null)
                return File(filename, "image/png");

            var userImageData = new byte[userImage.InputStream.Length];

            try
            {
                userImage.InputStream.Read(userImageData, 0, userImageData.Length);

                if (userImageData.Length ==0)
                    return File(filename, "image/png");

                if (HttpContext.Session["userImage"] != null)
                    HttpContext.Session.Remove("userImage");

                HttpContext.Session.Add("userImage", userImageData);
            }
            finally
            {
                userImage.InputStream.Close();
            }
            return File(userImageData, "image/png");
        }

        /// <summary>
        ///     Method to get the user image/photo
        /// </summary>
        /// <param name="userName">
        ///     Name of the user
        /// </param>
        /// <returns>
        ///     User image to be rendered on the screen
        /// </returns>
        public ActionResult UserImage(string userName)
        {
            var filename = Server.MapPath("~/") + @"Content\images\projHeadImg.png";
            try
            {
                if (HttpContext.Session["userImage"] == null)
                {
                    var image = _userProfileService.GetUserThumbnail(userName);
                    if (image != null)
                        return File(image, "image/png");
                }
                else
                {
                    var userImageData = (byte[])HttpContext.Session["userImage"];

                    if (userImageData != null)
                        return File(userImageData, "image/png");
                }
            }
            catch (InvalidCastException)
            {
                filename = Server.MapPath("~/") + @"Content\images\projHeadImg.png";
            }

            return File(filename, "image/png");
        }

        /// <summary>
        ///     Method deletes an item from the session-state collection.
        /// </summary>
        /// <param name="sessionName">
        ///     Session object to be removed
        /// </param>
        private void RemoveSession(string sessionName)
        {
            if (HttpContext.Session[sessionName] != null)
                HttpContext.Session.Remove(sessionName);
        }

        /// <summary>
        ///     Method to get the ideas submitted by the loggedin user
        /// </summary>
        /// <param name="page">
        ///     Current Page number
        /// </param>
        /// <returns>
        ///     View Model for ideas list
        /// </returns>
        [Authorize]
        public ActionResult Ideas(int? page)
        {
            IdeaListViewModel viewModel = new IdeaListViewModel
                                              {
                                                  Ideas = _userProfileService.GetSubmittedIdeas(User.Identity.Name, page.GetValueOrDefault(0).ToString(CultureInfo.CurrentCulture), _pageSize),
                                                  UserName = User.Identity.Name
                                              };
            return View(viewModel);
        }

        /// <summary>
        ///     Method to get the ideas marked as Favorite by the loggedin user
        /// </summary>
        /// <param name="page">
        ///     Current page number
        /// </param>
        /// <returns>
        ///     View Model for ideas list
        /// </returns>
        [Authorize]
        public ActionResult FavoriteIdeas(int? page)
        {
            IdeaListViewModel viewModel = new IdeaListViewModel
                                              {
                                                  Ideas = _userProfileService.GetFavoriteIdeas(User.Identity.Name, page.GetValueOrDefault(0).ToString(CultureInfo.CurrentCulture), _pageSize),
                                                  UserName = User.Identity.Name
                                              };
            return View(viewModel);
        }

        /// <summary>
        ///     Method to get the recommended ideas for the loggedin user
        /// </summary>
        /// <param name="page">
        ///     Current page number
        /// </param>
        /// <returns>
        ///     View Model for ideas list
        /// </returns>
        [Authorize]
        public ActionResult RecommendedIdeas(int? page)
        {
            IdeaListViewModel viewModel = new IdeaListViewModel
                                              {
                                                  Ideas = _userProfileService.GetRecommendedIdeas(User.Identity.Name, page.GetValueOrDefault(0).ToString(CultureInfo.CurrentCulture), _pageSize),
                                                  UserName = User.Identity.Name
                                              };
            return View(viewModel);
        }

        /// <summary>
        ///     Method to get the projects volunteered by the loggedin user
        /// </summary>
        /// <param name="page">
        ///     Current page number
        /// </param>
        /// <returns>
        ///    View Model for projects list
        /// </returns>
        [Authorize]
        public ActionResult Projects(int? page)
        {
            ProjectListViewModel viewModel = new ProjectListViewModel
                                                {
                                                    Projects = _userProfileService.GetVolunteeredProjects(User.Identity.Name, page.GetValueOrDefault(0).ToString(CultureInfo.CurrentCulture), _pageSize),
                                                    UserName = User.Identity.Name
                                                };
            return View(viewModel);
        }

        /// <summary>
        ///     Method to get the projects marked as Favorite by the loggedin user
        /// </summary>
        /// <param name="page">
        ///     Current page number
        /// </param>
        /// <returns>
        ///    View Model for projects list
        /// </returns>
        [Authorize]
        public ActionResult FavoriteProjects(int? page)
        {
            ProjectListViewModel viewModel = new ProjectListViewModel
                                                 {
                                                     Projects = _userProfileService.GetFavoriteProjects(User.Identity.Name, page.GetValueOrDefault(0).ToString(CultureInfo.CurrentCulture), _pageSize),
                                                     UserName = User.Identity.Name
                                                 };
            return View(viewModel);
        }

        /// <summary>
        ///     Method to get the recommended projects of the loggedin user
        /// </summary>
        /// <param name="page">
        ///     Current page number
        /// </param>
        /// <returns>
        ///    View Model for projects list
        /// </returns>
        [Authorize]
        public ActionResult RecommendedProjects(int? page)
        {
            ProjectListViewModel viewModel = new ProjectListViewModel
                                                 {
                                                     Projects = _userProfileService.GetRecommendedProjects(User.Identity.Name, page.GetValueOrDefault(0).ToString(CultureInfo.CurrentCulture), _pageSize),
                                                     UserName = User.Identity.Name
                                                 };
            return View(viewModel);
        }

        /// <summary>
        ///     Method to get the user profile
        /// </summary>
        /// <returns>
        ///     Model of the User Profile view
        /// </returns>
        [Authorize]
        public ActionResult Profile()
        {
            UserProfile user = _userProfileService.FindByUserName(User.Identity.Name );
            UserProfileViewModel viewModel = new UserProfileViewModel
            {
                User = user,
                UserInterests = user.UserInterests.InterestSummary()
            };
            RemoveSession("userImage");
            return View(viewModel);
        }
    }
}